﻿using FlyIL.Advance;
using FlyIL.Expression;
using FlyIL.Misc;
using FlyIL.Trace;


namespace FlyIL.Optimizer;



class PopPass : SimplfyRoot
{

    protected MovPass mov_pass;


    public override bool IsMatch(Context con, Inst node, ExpByTrace expression = null)
    {
        if (node.Opt == Opt.pop)
        {
            /// 具体该使用何种追踪， 追踪后是否需要再追踪比较 ？ 以及如何处理 仍需要 进一步优化考虑 

            _exp = con.TraceStrict(node, ref node.O1);
            /// 此处不能化简 
            return true;
        }

        return false;
    }


}

class PopPassWithExpAImm : PopPass
{

    public override bool IsMatch(Context con, Inst node, ExpByTrace expression = null)
       => expression != null && expression.Calculable;

    /**
     * 表达式是一个常量
     */
    public override void Do(Context con, Inst node, ExpByTrace expression = null)
    {
        mov_pass ??= new MovPass();
        Operand op = node.O1;

        con.NOP(node);
        node.mov(op, expression.Result);

        (mov_pass).Do(con, node);

    }

}

class PopPassWith1Op : PopPass
{

    public override bool IsMatch(Context con, Inst node, ExpByTrace expression = null)
       => expression != null && !expression.Calculable && expression.CalcDepth == 0;

    /**
     * 表达式不能计算 ， 仅有一个操作数 ，
     */
    public override void Do(Context con, Inst node, ExpByTrace expression = null)
    {

        /// pop 相当于 赋值， 则 hasChanged 可忽略
        if (expression == null || expression.HasTargetBeenUsed)
            return;


        mov_pass ??= new MovPass();


        Operand op = node.O1;
        var pushn = con.FindThePush(node);

        if (pushn == null)
            return;

        /*****************
         * 找到的 push节点， 与追踪到的 表达式， 操作数不一致的情况
         * push eax
         * mov [esp], ebx
         * pop ecx 
         * 
         * ***************/
        if (expression.FinalLeft<Operand>() != pushn.O1)
        {
            node.mov(node.O1, expression.FinalLeft<Operand>());
            var sp = con.RegSpExp;
            con.InsertBefore(node).lea(OperandMaker._regs_[sp], sp + node.O1.ByteSize);

             con.SimplifyOnce(con.GetPreviousIfExist(node)); 

            return;
        }
        else
        /// push 与 表达式一致 
        {

            /// !!!注意， 这里改为 优先修改 pop 节点 

            /// 在 push 和 pop 结点之间 ， 有被修改(不是直接值 ) ， 则不能 将 push 化简为 mov  
            if (con.HasAlter(pushn, node, ref op))
            {

            }

            con.NOP(node);
            con.RemoveDeadCode(node, ref node.O1);


            /// ??? 原来是干啥来着 
            if (op != expression.FinalLeft<Operand>())
            {
                /// 应该修改 push 为 mov 
                /// it0.mov(op, Operand.Make((RegCode)exp.Left));
                node.mov(op, expression.FinalLeft<Operand>());
            }
        }
    }
}
class PopPassWithExpNormal : PopPass
{

    public override bool IsMatch(Context con, Inst node, ExpByTrace expression = null)
       => expression != null && !expression.Calculable && expression.CalcDepth > 0;

    /**
     * 普通表达式
     */
    public override void Do(Context con, Inst node, ExpByTrace expression = null)
    {
        mov_pass ??= new MovPass();
        Operand op = node.O1;

        /// 此处重新编译， 为了将 push pop ,化简为 mov, xxx 
        var simp = expression.Copy();
        simp.Simplify();

        /// 化简不会 影响到 原始汇编
        if (con.IsExpIndependent(expression))
            con.CompileWithStack(node, expression, simp);
    }
}
